/*************************************************
* Title：TinyToolKit
* Author：Opportunity 
* Discribe：实现有限状态机管理器的主要逻辑
* CreateTime：2020-04-05 21:28:43
* Version：1.0
* Modify Recoder：
*************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace TinyToolKit.FSM
{
    //有限状态机管理器
    public class TFsmManager : ManagerBase, IFsmManager
    {
        private Dictionary<string, FsmSystemBase> _fsms;

        /// <summary>
        /// 获取有限状态机的数量
        /// </summary>
        /// <value>返回有限状态机的数量</value>
        public int FsmCount => _fsms.Count;

        #region Manager Base
        public override int Priority => 60;

        public override void Init()
        {
            _fsms = new Dictionary<string, FsmSystemBase>();
        }

        public override void UpdateManager()
        {
            if (_fsms.Count <= 0) return;

            foreach (KeyValuePair<string, FsmSystemBase> fsmItem in _fsms)
            {
                if(fsmItem.Value.IsDestroyed == false)
                    fsmItem.Value.Update();
            }
        }

        public override void Shutdown()
        {
            foreach (KeyValuePair<string, FsmSystemBase> fsm in _fsms)
            {
                fsm.Value.Shutdown();
            }

            _fsms.Clear();
        }
        #endregion

        #region Create FSM
        /// <summary>
        /// 创建有限状态机
        /// </summary>
        /// <returns>返回创建的状态机</returns>
        /// <param name="name">有限状态机的名字</param>
        /// <param name="owner">有限状态机的持有者</param>
        /// <param name="states">有限状态机的状态</param>
        /// <typeparam name="T">有限状态机持有者的类型</typeparam>
        public IFsmSystem<T> CreateFsm<T>(string name, T owner, params FsmState<T>[] states) where T : class
        {
            List<FsmState<T>> statesList = new List<FsmState<T>>(states);
            return CreateFsm(name, owner, statesList);
        }

        /// <summary>
        /// Creates the fsm.
        /// </summary>
        /// <returns>The fsm.</returns>
        /// <param name="name">Name.</param>
        /// <param name="owner">Owner.</param>
        /// <param name="states">States.</param>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        public IFsmSystem<T> CreateFsm<T>(string name, T owner, List<FsmState<T>> states) where T : class
        {
            string fsmName = GetFsmFullName<T>(name);

            if (HasFsm<T>(name))
            {
                TLogTool.Error("已经存在FSM：" + fsmName);
                return null;
            }

            //可能需要创建大量的FSM，采用类对象池(引用池)获取类
            FsmSystem<T> fsm = TReferencePool.Acquire<FsmSystem<T>>();
            fsm.Create(name, owner, states);
            _fsms.Add(fsmName, fsm);
            return fsm;
        }

        #endregion

        #region Has FSM
        /// <summary>
        /// 判断是否存在有限状态机
        /// </summary>
        /// <returns><c>true</c>, 有限状态机存在, <c>false</c> 该有限状态机不存在</returns>
        /// <param name="name">查询的有限状态机的名字</param>
        /// <typeparam name="T">该有限状态机持有者的类型</typeparam>
        public bool HasFsm<T>(string name) where T : class
        {
            return InternalHasFsm(GetFsmFullName<T>(name));
        }

        /// <summary>
        /// 判断是否存在有限状态机
        /// </summary>
        /// <returns><c>true</c>, 有限状态机存在, <c>false</c> 该有限状态机不存在</returns>
        /// <param name="ownerType">该有限状态机持有者的类型</param>
        /// <param name="name">查询的有限状态机的名字</param>
        public bool HasFsm(Type ownerType, string name)
        {
            if (ownerType == null) return false;
            return InternalHasFsm(GetFsmFullName(ownerType, name));
        }
        #endregion 

        #region Get FSM
        /// <summary>
        /// 获取有限状态机
        /// </summary>
        /// <returns>返回需要的有限状态机</returns>
        /// <param name="name">有限状态机的名字</param>
        /// <typeparam name="T">有限状态机持有的类型</typeparam>
        public IFsmSystem<T> GetFsm<T>(string name) where T : class
        {
            return InternalGetFsm(GetFsmFullName<T>(name)) as IFsmSystem<T>;
        }

        /// <summary>
        /// 获取有限状态机
        /// </summary>
        /// <returns>返回需要的有限状态机</returns>
        /// <param name="ownerType">有限状态机持有的类型</param>
        /// <param name="name">有限状态机的名字</param>
        public FsmSystemBase GetFsm(Type ownerType, string name)
        {
            if (ownerType == null) return null;
            return InternalGetFsm(GetFsmFullName(ownerType, name));
        }

        /// <summary>
        /// 获取所有有限状态机
        /// </summary>
        /// <returns>所有的有限状态机</returns>
        public FsmSystemBase[] GetAllFsms()
        {
            int index = 0;
            FsmSystemBase[] fsms = new FsmSystemBase[_fsms.Count];
            foreach (KeyValuePair<string, FsmSystemBase> fsm in _fsms)
            {
                fsms[index++] = fsm.Value;
            }
            return fsms;
        }

        /// <summary>
        /// 获取所有有限状态机,fsms不能为Null
        /// </summary>
        /// <param name="fsms">存储所有有限状态机的列表</param>
        public void GetAllFsms(List<FsmSystemBase> fsms)
        {
            if (fsms == null) return;
            fsms.Clear();

            foreach (KeyValuePair<string, FsmSystemBase> fsm in _fsms)
            {
                fsms.Add(fsm.Value);
            }
        }
        #endregion

        #region Destroy FSM
        /// <summary>
        /// 销毁有限状态机
        /// </summary>
        /// <returns><c>true</c>, 该有限状态机被销毁, <c>false</c> 未被销毁.</returns>
        /// <param name="fsm">需要被销毁的有限状态机</param>
        public bool DestroyFsm(FsmSystemBase fsm)
        {
            if (fsm == null) return false;
            return InternalDestroyFsm(GetFsmFullName(fsm.OwnerType, fsm.Name));
        }

        /// <summary>
        /// 销毁有限状态机
        /// </summary>
        /// <returns><c>true</c>, 该有限状态机被销毁, <c>false</c> 未被销毁.</returns>
        /// <param name="ownerType">持有者的类型</param>
        /// <param name="name">有限状态机的名字</param>
        public bool DestroyFsm(Type ownerType, string name)
        {
            if (ownerType == null) return false;
            return InternalDestroyFsm(GetFsmFullName(ownerType, name));
        }

        /// <summary>
        /// 销毁有限状态机
        /// </summary>
        /// <returns><c>true</c>, 该有限状态机被销毁, <c>false</c> 未被销毁</returns>
        /// <param name="name">有限状态机的名字</param>
        /// <typeparam name="T">持有者的类型</typeparam>
        public bool DestroyFsm<T>(string name) where T : class
        {
            return InternalDestroyFsm(GetFsmFullName<T>(name));
        }

        /// <summary>
        /// 销毁有限状态机
        /// </summary>
        /// <returns><c>true</c>, 该有限状态机被销毁, <c>false</c> 未被销毁</returns>
        /// <param name="fsm">需要被销毁的有限状态机</param>
        /// <typeparam name="T">持有者的类型</typeparam>
        public bool DestroyFsm<T>(IFsmSystem<T> fsm) where T : class
        {
            if (fsm == null) return false;
            return InternalDestroyFsm(GetFsmFullName<T>(fsm.Name));
        }
        #endregion

        #region Helper Method
        private string GetFsmFullName(Type type, string name)
        {
            string fsmName = type.FullName;
            if (name != string.Empty)
                fsmName = $"{fsmName}.{name}";
            return fsmName;
        }

        private string GetFsmFullName<T>(string name) where T : class
        {
            return GetFsmFullName(typeof(T), name);
        }

        private bool InternalHasFsm(string fullName)
        {
            return _fsms.ContainsKey(fullName);
        }

        private FsmSystemBase InternalGetFsm(string fullName)
        {
            if (_fsms.TryGetValue(fullName, out var fsm))
                return fsm;
            return null;
        }

        private bool InternalDestroyFsm(string fullName)
        {
            if (_fsms.TryGetValue(fullName, out var fsm))
            {
                fsm.Shutdown();
                return _fsms.Remove(fullName);
            }
            return false;
        }
        #endregion
    }
}

